home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / dwinst.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  22.5 KB  |  940 lines

  1. /* Copyright (C) 1999, Ghostgum Software Pty Ltd.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. // $Id: dwinst.cpp,v 1.2 2000/09/19 19:00:09 lpd Exp $
  20.  
  21. #define STRICT
  22. #include <windows.h>
  23. #include <objbase.h>
  24. #include <shlobj.h>
  25. #include <stdio.h>
  26. #include <io.h>
  27. #include <direct.h>
  28.  
  29. #include "dwinst.h"
  30.  
  31. #define UNINSTALLKEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
  32. #define UNINSTALLSTRINGKEY TEXT("UninstallString")
  33. #define DISPLAYNAMEKEY TEXT("DisplayName")
  34. #define UNINSTALL_FILE "uninstal.txt"
  35. char szSection[] = "////////////////////////////////\n";
  36.  
  37. #ifdef _MSC_VER
  38. #define mktemp(x) _mktemp(x)
  39. #define chdir(x) _chdir(x)
  40. #define mkdir(x) _mkdir(x)
  41. #endif
  42.  
  43.  
  44.  
  45. //////////////////////////////////////////////////////////////////////
  46. // Construction/Destruction
  47. //////////////////////////////////////////////////////////////////////
  48.  
  49. CInstall::CInstall()
  50. {
  51.     CoInitialize(NULL);
  52.     
  53.     m_szTargetDir[0] = '\0';
  54.     m_szTargetGroup[0] = '\0';
  55.     m_szPrograms[0] = '\0';
  56.     m_szMainDir[0] = '\0';
  57.     AddMessageFn = NULL;
  58.     SetAllUsers(FALSE);
  59. }
  60.  
  61. CInstall::~CInstall()
  62. {
  63.     CoUninitialize();
  64. }
  65.  
  66. void CInstall::CleanUp(void)
  67. {
  68.     // delete all temporary files
  69.     if (m_fLogNew)
  70.         fclose(m_fLogNew);
  71.     m_fLogNew = NULL;
  72.     if (m_fLogOld)
  73.         fclose(m_fLogOld);
  74.     m_fLogOld = NULL;
  75.     
  76.     if (strlen(m_szRegistryNew))
  77.         DeleteFile(m_szRegistryNew);
  78.     m_szRegistryNew[0] = '\0';
  79.     
  80.     if (strlen(m_szRegistryOld))
  81.         DeleteFile(m_szRegistryOld);
  82.     m_szRegistryOld[0] = '\0';
  83.     
  84.     if (strlen(m_szShellNew))
  85.         DeleteFile(m_szShellNew);
  86.     m_szShellNew[0] = '\0';
  87.     
  88.     if (strlen(m_szShellOld))
  89.         DeleteFile(m_szShellOld);
  90.     m_szShellOld[0] = '\0';
  91.     
  92.     if (strlen(m_szFileNew))
  93.         DeleteFile(m_szFileNew);
  94.     m_szFileNew[0] = '\0';
  95. }
  96.  
  97.  
  98. void CInstall::SetMessageFunction(void(*fn)(const char *))
  99. {
  100.     AddMessageFn = fn;
  101. }
  102.  
  103. void CInstall::AddMessage(const char *message)
  104. {
  105.     if (AddMessageFn)
  106.         (*AddMessageFn)(message);
  107. }
  108.  
  109. void CInstall::SetTargetDir(const char *szTargetDir)
  110. {
  111.     strcpy(m_szTargetDir, szTargetDir);
  112.     // remove trailing backslash
  113.     char *p;
  114.     p = m_szTargetDir + strlen(m_szTargetDir) - 1;
  115.     if (*p == '\\')
  116.         *p = '\0';
  117. }
  118.  
  119. void CInstall::SetTargetGroup(const char *szTargetGroup)
  120. {
  121.     strcpy(m_szTargetGroup, szTargetGroup);
  122.     // remove trailing backslash
  123.     char *p;
  124.     p = m_szTargetGroup + strlen(m_szTargetGroup) - 1;
  125.     if (*p == '\\')
  126.         *p = '\0';
  127. }
  128.  
  129. const char *CInstall::GetMainDir()
  130. {
  131.     return m_szMainDir;
  132. }
  133.  
  134. const char *CInstall::GetUninstallName()
  135. {
  136.     return m_szUninstallName;
  137. }
  138.  
  139. BOOL CInstall::Init(const char *szSourceDir, const char *szFileList)
  140. {
  141.     FILE *f;
  142.     
  143.     strcpy(m_szSourceDir, szSourceDir);
  144.     // remove trailing backslash
  145.     char *p;
  146.     p = m_szSourceDir + strlen(m_szSourceDir) - 1;
  147.     if (*p == '\\')
  148.         *p = '\0';
  149.     strcpy(m_szFileList, szFileList);
  150.     
  151.     m_szRegistryNew[0] = m_szRegistryOld[0] = 
  152.         m_szShellNew[0] = m_szShellOld[0] = 
  153.         m_szFileNew[0] = '\0';
  154.     
  155.     // Open list of files
  156.     SetCurrentDirectory(m_szSourceDir);
  157.     f = fopen(m_szFileList, "r");
  158.     if (f == (FILE *)NULL) {
  159.         char buf[MAXSTR];
  160.         wsprintf(buf, "Failed to open \042%s\042\n", m_szFileList);
  161.         AddMessage(buf);
  162.         return FALSE;
  163.     }
  164.     
  165.     // get application and directory name
  166.     m_szUninstallName[0] = '\0';
  167.     if (!fgets(m_szUninstallName, sizeof(m_szUninstallName), f)) {
  168.         AddMessage("Invalid file list\n");
  169.         fclose(f);
  170.         return FALSE;
  171.     }
  172.     if (*m_szUninstallName )
  173.         m_szUninstallName[strlen(m_szUninstallName)-1] = '\0';
  174.     
  175.     m_szMainDir[0] = '\0';
  176.     if (!fgets(m_szMainDir, sizeof(m_szMainDir), f)) {
  177.         AddMessage("Invalid file list\n");
  178.         fclose(f);
  179.         return FALSE;
  180.     }
  181.     if (*m_szMainDir )
  182.         m_szMainDir[strlen(m_szMainDir)-1] = '\0';
  183.     fclose(f);
  184.     
  185.     // Create log directory
  186.     strcpy(m_szLogDir, m_szTargetDir);
  187.     strcat(m_szLogDir, "\\");
  188.     strcat(m_szLogDir, m_szMainDir);
  189.     MakeDir(m_szLogDir);
  190.     
  191.     return TRUE;
  192. }
  193.  
  194.  
  195. //////////////////////////////////////////
  196. // File installation methods
  197.  
  198. BOOL CInstall::InstallFiles(BOOL bNoCopy, BOOL *pbQuit)
  199. {
  200.     char szLogNew[MAXSTR];
  201.     
  202.     AddMessage(bNoCopy ? "Checking" : "Copying");
  203.     AddMessage(" files listed in ");
  204.     AddMessage(m_szFileList);
  205.     AddMessage("\n");
  206.     
  207.     // Open list of files
  208.     SetCurrentDirectory(m_szSourceDir);
  209.     FILE *f = fopen(m_szFileList, "r");
  210.     if (f == (FILE *)NULL) {
  211.         AddMessage("Failed to open \042");
  212.         AddMessage(m_szFileList);
  213.         AddMessage("\042\n");
  214.         return FALSE;
  215.     }
  216.     
  217.     // skip application and directory name
  218.     fgets(szLogNew, sizeof(szLogNew), f);
  219.     fgets(szLogNew, sizeof(szLogNew), f);
  220.     
  221.     // Create target log
  222.     
  223.     m_fLogNew = MakeTemp(m_szFileNew);
  224.     if (!m_fLogNew) {
  225.         AddMessage("Failed to create FileNew temporary file\n");
  226.         return FALSE;
  227.     }
  228.     
  229.     // Copy files
  230.     char line[MAXSTR];
  231.     while (fgets(line, sizeof(line), f) != (char *)NULL) {
  232.         if (*pbQuit)
  233.             return FALSE;
  234.         if (*line)
  235.             line[strlen(line)-1] = '\0';
  236.         if (!InstallFile(line, bNoCopy)) {
  237.             fclose(f);
  238.             fclose(m_fLogNew);
  239.             return FALSE;
  240.         }
  241.     }
  242.     fclose(f);
  243.     fclose(m_fLogNew);
  244.     m_fLogNew = NULL;
  245.     return TRUE;
  246. }
  247.  
  248.  
  249.  
  250. // recursive mkdir
  251. // requires a full path to be specified, so ignores root \ 
  252. // apart from root \, must not contain trailing \
  253. // Examples:
  254. //  c:\          (OK, but useless)
  255. //  c:\gstools   (OK)
  256. //  c:\gstools\  (incorrect)
  257. //  c:gstools    (incorrect)
  258. //  gstools      (incorrect)
  259. // The following UNC names should work,
  260. // but didn't under Win3.1 because gs_chdir wouldn't accept UNC names
  261. // Needs to be tested under Windows 95.
  262. //  \\server\sharename\gstools    (OK)
  263. //  \\server\sharename\           (OK, but useless)
  264. //
  265.  
  266. BOOL CInstall::MakeDir(const char *dirname)
  267. {
  268.     char newdir[MAXSTR];
  269.     const char *p;
  270.     if (strlen(dirname) < 3)
  271.         return -1;
  272.     
  273.     if (isalpha(dirname[0]) && dirname[1]==':' && dirname[2]=='\\') {
  274.         // drive mapped path
  275.         p = dirname+3;
  276.     }
  277.     else if (dirname[1]=='\\' && dirname[1]=='\\') {
  278.         // UNC path
  279.         p = strchr(dirname+2, '\\');    // skip servername
  280.         if (p == NULL)
  281.             return -1;
  282.         p++;
  283.         p = strchr(p, '\\');            // skip sharename
  284.         if (p == NULL)
  285.             return -1;
  286.     }
  287.     else {
  288.         // not full path so error
  289.         return -1;
  290.     }
  291.     
  292.     while (1) {
  293.         strncpy(newdir, dirname, (int)(p-dirname));
  294.         newdir[(int)(p-dirname)] = '\0';
  295.         if (chdir(newdir)) {
  296.             if (mkdir(newdir))
  297.                 return -1;
  298.         }
  299.         p++;
  300.         if (p >= dirname + strlen(dirname))
  301.             break;              // all done
  302.         p = strchr(p, '\\');
  303.         if (p == NULL)
  304.             p = dirname + strlen(dirname);
  305.     }
  306.     
  307.     return SetCurrentDirectory(dirname);
  308. }
  309.  
  310. BOOL CInstall::InstallFile(char *filename, BOOL bNoCopy)
  311. {
  312.     char existing_name[MAXSTR];
  313.     char new_name[MAXSTR];
  314.     char dir_name[MAXSTR];
  315.     
  316.     strcpy(existing_name, m_szSourceDir);
  317.     strcat(existing_name, "\\");
  318.     strcat(existing_name, filename);
  319.     strcpy(new_name, m_szTargetDir);
  320.     strcat(new_name, "\\");
  321.     strcat(new_name, filename);
  322.     strcpy(dir_name, new_name);
  323.     char *p = strrchr(dir_name, '\\');
  324.     if (p) {
  325.         *p = '\0';
  326.         if (!MakeDir(dir_name)) {
  327.             AddMessage("Failed to make directory ");
  328.             AddMessage(dir_name);
  329.             AddMessage("\n");
  330.             return FALSE;
  331.         }
  332.     }
  333.     AddMessage("   ");
  334.     AddMessage(new_name);
  335.     AddMessage("\n");
  336.     
  337.     if (bNoCopy) {
  338.         // Don't copy files.  Leave them where they are.
  339.         // Check that all files exist
  340.         FILE *f;
  341.         if ((f = fopen(existing_name, "r")) == (FILE *)NULL) {
  342.             AddMessage("Missing file ");
  343.             AddMessage(existing_name);
  344.             AddMessage("\n");
  345.             return FALSE;
  346.         }
  347.         fclose(f);
  348.     }
  349.     else {
  350.         if (!CopyFile(existing_name, new_name, FALSE)) {
  351.             char message[MAXSTR+MAXSTR+100];
  352.             wsprintf(message, "Failed to copy file %s to %s\n", 
  353.                 existing_name, new_name);
  354.             AddMessage(message);
  355.             return FALSE;
  356.         }
  357.         fputs(new_name, m_fLogNew);
  358.         fputs("\n", m_fLogNew);
  359.     }
  360.     
  361.     
  362.     return TRUE;
  363. }
  364.  
  365. //////////////////////////////////////////
  366. // Shell methods
  367.  
  368. BOOL CInstall::StartMenuBegin()
  369. {
  370.     m_fLogNew = MakeTemp(m_szShellNew);
  371.     if (!m_fLogNew) {
  372.         AddMessage("Failed to create ShellNew temporary file\n");
  373.         return FALSE;
  374.     }
  375.     
  376.     m_fLogOld = MakeTemp(m_szShellOld);
  377.     if (!m_fLogOld) {
  378.         AddMessage("Failed to create ShellNew temporary file\n");
  379.         return FALSE;
  380.     }
  381.     
  382.     // make folder if needed
  383.     char szLink[MAXSTR];
  384.     strcpy(szLink, m_szPrograms);
  385.     strcat(szLink, "\\");
  386.     strcat(szLink, m_szTargetGroup);
  387.     if (chdir(szLink) != 0) {
  388.         if (mkdir(szLink) != 0) {
  389.             char buf[MAXSTR+64];
  390.             wsprintf(buf, "Couldn't make Programs folder \042%s'042", szLink);
  391.             AddMessage(buf);
  392.             StartMenuEnd();
  393.             return FALSE;
  394.         }
  395.     }
  396.     else {
  397.         fprintf(m_fLogOld, "Group=%s\n\n", szLink);
  398.     }
  399.     fprintf(m_fLogNew, "Group=%s\n\n", szLink);
  400.     
  401.     return TRUE;
  402. }
  403.  
  404. BOOL CInstall::StartMenuEnd()
  405. {
  406.     if (m_fLogOld)
  407.         fclose(m_fLogOld);
  408.     m_fLogOld = NULL;
  409.     if (m_fLogNew)
  410.         fclose(m_fLogNew);
  411.     m_fLogNew = NULL;
  412.     return TRUE;
  413. }
  414.  
  415. BOOL CInstall::StartMenuAdd(const char *szDescription, 
  416.                             const char *szProgram, const char *szArguments) 
  417. {
  418.     if (!CreateShellLink(szDescription, szProgram, szArguments)) {
  419.         AddMessage("Couldn't make shell link for ");
  420.         AddMessage(szDescription);
  421.         AddMessage("\n");
  422.         StartMenuEnd();
  423.         return FALSE;
  424.     }
  425.     
  426.     return TRUE;
  427. }
  428.  
  429.  
  430. BOOL CInstall::CreateShellLink(LPCSTR description, LPCSTR program, 
  431.                                LPCSTR arguments, LPCSTR icon, int nIconIndex)
  432. {
  433.     HRESULT hres;    
  434.     IShellLink* psl;
  435.     CHAR szLink[MAXSTR];
  436.     strcpy(szLink, m_szPrograms);
  437.     strcat(szLink, "\\");
  438.     strcat(szLink, m_szTargetGroup);
  439.     strcat(szLink, "\\");
  440.     strcat(szLink, description);
  441.     strcat(szLink, ".LNK");
  442.     AddMessage("Adding shell link\n   ");
  443.     AddMessage(szLink);
  444.     AddMessage("\n");
  445.     
  446.     // Ensure string is UNICODE.
  447.     WCHAR wsz[MAX_PATH];
  448.     MultiByteToWideChar(CP_ACP, 0, szLink, -1, wsz, MAX_PATH);
  449.     
  450.     // Save old shell link
  451.     
  452.     // Get a pointer to the IShellLink interface.
  453.     hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  454.         IID_IShellLink, (void **)&psl);
  455.     if (SUCCEEDED(hres))    {
  456.         IPersistFile* ppf;
  457.         // Query IShellLink for the IPersistFile interface.
  458.         hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
  459.         if (SUCCEEDED(hres))       {            
  460.             // Load the shell link.
  461.             hres = ppf->Load(wsz, STGM_READ);
  462.             if (SUCCEEDED(hres)) {
  463.                 // Resolve the link.
  464.                 hres = psl->Resolve(HWND_DESKTOP, SLR_ANY_MATCH);       
  465.                 if (SUCCEEDED(hres)) {
  466.                     // found it, so save details
  467.                     CHAR szTemp[MAXSTR];
  468.                     WIN32_FIND_DATA wfd;
  469.                     int i;
  470.                     
  471.                     
  472.                     fprintf(m_fLogOld, "Name=%s\n", szLink);
  473.                     hres = psl->GetPath(szTemp, MAXSTR, (WIN32_FIND_DATA *)&wfd, 
  474.                         SLGP_SHORTPATH );
  475.                     if (SUCCEEDED(hres))
  476.                         fprintf(m_fLogOld, "Path=%s\n", szTemp);
  477.                     hres = psl->GetDescription(szTemp, MAXSTR);
  478.                     if (SUCCEEDED(hres))
  479.                         fprintf(m_fLogOld, "Description=%s\n", szTemp);
  480.                     hres = psl->GetArguments(szTemp, MAXSTR);
  481.                     if (SUCCEEDED(hres) && (szTemp[0] != '\0'))
  482.                         fprintf(m_fLogOld, "Arguments=%s\n", szTemp);
  483.                     hres = psl->GetWorkingDirectory(szTemp, MAXSTR);
  484.                     if (SUCCEEDED(hres) && (szTemp[0] != '\0'))
  485.                         fprintf(m_fLogOld, "Directory=%s\n", szTemp);
  486.                     hres = psl->GetIconLocation(szTemp, MAXSTR, &i);
  487.                     if (SUCCEEDED(hres) && (szTemp[0] != '\0')) {
  488.                         fprintf(m_fLogOld, "IconLocation=%s\n", szTemp);
  489.                         fprintf(m_fLogOld, "IconIndex=%d\n", i);
  490.                     }
  491.                     fprintf(m_fLogOld, "\n");
  492.                 }      
  493.             }
  494.             // Release pointer to IPersistFile.         
  495.             ppf->Release();       
  496.         }
  497.         // Release pointer to IShellLink.       
  498.         psl->Release();    
  499.     }
  500.     
  501.     
  502.     // Save new shell link
  503.     
  504.     // Get a pointer to the IShellLink interface.
  505.     hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  506.         IID_IShellLink, (void **)&psl);
  507.     if (SUCCEEDED(hres))    {
  508.         IPersistFile* ppf;
  509.         // Query IShellLink for the IPersistFile interface for 
  510.         // saving the shell link in persistent storage.
  511.         hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
  512.         if (SUCCEEDED(hres)) {            
  513.             fprintf(m_fLogNew, "Name=%s\n", szLink);
  514.             
  515.             // Set the path to the shell link target.
  516.             hres = psl->SetPath(program);         
  517.             if (!SUCCEEDED(hres))
  518.                 AddMessage("SetPath failed!");
  519.             fprintf(m_fLogNew, "Path=%s\n", program);
  520.             // Set the description of the shell link.
  521.             hres = psl->SetDescription(description);         
  522.             if (!SUCCEEDED(hres))
  523.                 AddMessage("SetDescription failed!");
  524.             fprintf(m_fLogNew, "Description=%s\n", description);
  525.             if (arguments != (LPCSTR)NULL) {
  526.                 // Set the arguments of the shell link target.
  527.                 hres = psl->SetArguments(arguments);         
  528.                 if (!SUCCEEDED(hres))
  529.                     AddMessage("SetArguments failed!");
  530.                 fprintf(m_fLogNew, "Arguments=%s\n", arguments);
  531.             }
  532.             if (icon != (LPCSTR)NULL) {
  533.                 // Set the arguments of the shell link target.
  534.                 hres = psl->SetIconLocation(icon, nIconIndex);         
  535.                 if (!SUCCEEDED(hres))
  536.                     AddMessage("SetIconLocation failed!");
  537.                 fprintf(m_fLogNew, "IconLocation=%s\n", icon);
  538.                 fprintf(m_fLogNew, "IconIndex=%d\n", nIconIndex);
  539.             }
  540.             
  541.             // Save the link via the IPersistFile::Save method.
  542.             hres = ppf->Save(wsz, TRUE);    
  543.             // Release pointer to IPersistFile.         
  544.             ppf->Release();
  545.         }
  546.         // Release pointer to IShellLink.       
  547.         psl->Release();    
  548.         fprintf(m_fLogNew, "\n");
  549.     }
  550.     
  551.     return (hres == 0);
  552. }
  553.  
  554.  
  555. //////////////////////////////////////////
  556. // Registry methods
  557.  
  558. void
  559. reg_quote(char *d, const char *s)
  560. {
  561.     while (*s) {
  562.         if (*s == '\\')
  563.             *d++ = '\\';
  564.         *d++ = *s++;
  565.     }
  566.     *d = *s;
  567. }
  568.  
  569. BOOL CInstall::UpdateRegistryBegin()
  570. {
  571.     const char regheader[]="REGEDIT4\n";
  572.     m_fLogNew = MakeTemp(m_szRegistryNew);
  573.     if (!m_fLogNew) {
  574.         AddMessage("Failed to create RegistryNew temporary file\n");
  575.         return FALSE;
  576.     }
  577.     fputs(regheader, m_fLogNew);
  578.     
  579.     m_fLogOld = MakeTemp(m_szRegistryOld);
  580.     if (!m_fLogOld) {
  581.         AddMessage("Failed to create RegistryOld temporary file\n");
  582.         UpdateRegistryEnd();
  583.         return FALSE;
  584.     }
  585.     fputs(regheader, m_fLogOld);
  586.     
  587.     return TRUE;
  588. }
  589.  
  590. BOOL CInstall::UpdateRegistryEnd()
  591. {
  592.     if (m_fLogNew)
  593.         fclose(m_fLogNew);
  594.     m_fLogNew = NULL;
  595.     if (m_fLogOld)
  596.         fclose(m_fLogOld);
  597.     m_fLogOld = NULL;
  598.     return TRUE;
  599. }
  600.  
  601. BOOL CInstall::UpdateRegistryKey(const char *product, const char *version)
  602. {
  603.     const char hkey_name[] = "HKEY_LOCAL_MACHINE";
  604.     const HKEY hkey_key = HKEY_LOCAL_MACHINE;
  605.     const char key_format[] = "\n[%s\\%s]\n";
  606.     
  607.     /* Create default registry entries */
  608.     HKEY hkey;
  609.     LONG lrc;
  610.     char name[MAXSTR];
  611.     
  612.     // Create/Open application key
  613.     sprintf(name, "SOFTWARE\\%s", product);
  614.     lrc = RegOpenKey(hkey_key, name, &hkey);
  615.     if (lrc == ERROR_SUCCESS) {
  616.         fprintf(m_fLogOld, key_format, hkey_name, name);
  617.     }
  618.     else {
  619.         lrc = RegCreateKey(hkey_key, name, &hkey);
  620.         if (lrc == ERROR_SUCCESS)
  621.             fprintf(m_fLogNew, key_format, hkey_name, name);
  622.     }
  623.     if (lrc == ERROR_SUCCESS)
  624.         RegCloseKey(hkey);
  625.     
  626.     // Create/Open application version key
  627.     sprintf(name, "SOFTWARE\\%s\\%s", product, version);
  628.     
  629.     AddMessage("   ");
  630.     AddMessage(hkey_name);
  631.     AddMessage("\\");
  632.     AddMessage(name);
  633.     AddMessage("\n");
  634.     lrc = RegOpenKey(hkey_key, name, &hkey);
  635.     if (lrc == ERROR_SUCCESS)
  636.         fprintf(m_fLogOld, key_format, hkey_name, name);
  637.     else 
  638.         lrc = RegCreateKey(hkey_key, name, &hkey);
  639.     if (lrc == ERROR_SUCCESS) {
  640.         fprintf(m_fLogNew, key_format, hkey_name, name);
  641.     }
  642.     else {
  643.         UpdateRegistryEnd();
  644.     }
  645.     return TRUE;
  646. }
  647.  
  648. BOOL CInstall::UpdateRegistryValue(const char *product, const char *version, 
  649.                                    const char *name, const char *value)
  650. {
  651.     char appver[MAXSTR];
  652.     BOOL flag = FALSE;
  653.     HKEY hkey;
  654.     // Open application/version key
  655.     sprintf(appver, "SOFTWARE\\%s\\%s", product, version);
  656.     
  657.     if (RegOpenKey(HKEY_LOCAL_MACHINE, appver, &hkey)
  658.         == ERROR_SUCCESS) {
  659.         flag = SetRegistryValue(hkey, name, value);
  660.         RegCloseKey(hkey);
  661.     }
  662.     
  663.     return flag;
  664. }
  665.  
  666. BOOL CInstall::SetRegistryValue(HKEY hkey, const char *value_name, const char *value)
  667. {
  668.     char buf[MAXSTR];
  669.     char qbuf[MAXSTR];
  670.     DWORD cbData;
  671.     DWORD keytype;
  672.     
  673.     cbData = sizeof(buf);
  674.     keytype =  REG_SZ;
  675.     if (RegQueryValueEx(hkey, value_name, 0, &keytype, 
  676.         (LPBYTE)buf, &cbData) == ERROR_SUCCESS) {
  677.         reg_quote(qbuf, buf);
  678.         fprintf(m_fLogOld, "\042%s\042=\042%s\042\n", value_name, qbuf);
  679.     }
  680.     reg_quote(qbuf, value);
  681.     fprintf(m_fLogNew, "\042%s\042=\042%s\042\n", value_name, qbuf);
  682.     AddMessage("      ");
  683.     AddMessage(value_name);
  684.     AddMessage("=");
  685.     AddMessage(value);
  686.     AddMessage("\n");
  687.     if (RegSetValueEx(hkey, value_name, 0, REG_SZ, 
  688.         (CONST BYTE *)value, strlen(value)+1) != ERROR_SUCCESS)
  689.         return FALSE;
  690.     return TRUE;
  691. }
  692.  
  693. ////////////////////////////////////
  694. // Uninstall
  695.  
  696.  
  697. BOOL CInstall::WriteUninstall(const char *szProg, BOOL bNoCopy)
  698. {
  699.     LONG rc;
  700.     HKEY hkey;
  701.     HKEY hsubkey;
  702.     char buffer[MAXSTR];
  703.     char ungsprog[MAXSTR];
  704.     
  705.     lstrcpy(ungsprog, m_szTargetDir);
  706.     lstrcat(ungsprog, "\\");
  707.     lstrcat(ungsprog, szProg);
  708.     
  709.     lstrcpy(buffer, m_szSourceDir);
  710.     lstrcat(buffer, "\\");
  711.     lstrcat(buffer, szProg);
  712.     
  713.     if (bNoCopy) {
  714.         // Don't copy files.  Leave them where they are.
  715.         // Check that all files exist
  716.         FILE *f;
  717.         if ((f = fopen(buffer, "r")) == (FILE *)NULL) {
  718.             AddMessage("Missing file ");
  719.             AddMessage(buffer);
  720.             AddMessage("\n");
  721.             return FALSE;
  722.         }
  723.         fclose(f);
  724.     }
  725.     else if (!CopyFile(buffer, ungsprog, FALSE)) {
  726.         char message[MAXSTR+MAXSTR+100];
  727.         wsprintf(message, "Failed to copy file %s to %s", buffer, ungsprog);
  728.         AddMessage(message);
  729.         return FALSE;
  730.     }
  731.     
  732.     /* write registry entries for uninstall */
  733.     if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, UNINSTALLKEY, 0, 
  734.         KEY_ALL_ACCESS, &hkey)) != ERROR_SUCCESS) {
  735.         /* failed to open key, so try to create it */
  736.         rc = RegCreateKey(HKEY_LOCAL_MACHINE, UNINSTALLKEY, &hkey);
  737.     }
  738.     if (rc == ERROR_SUCCESS) {
  739.         // Uninstall key for program
  740.         if (RegCreateKey(hkey, m_szUninstallName, &hsubkey) == ERROR_SUCCESS) {
  741.             RegSetValueEx(hsubkey, DISPLAYNAMEKEY, 0, REG_SZ,
  742.                 (CONST BYTE *)m_szUninstallName, lstrlen(m_szUninstallName)+1);
  743.             lstrcpy(buffer, ungsprog);
  744.             lstrcat(buffer, " \042");
  745.             lstrcat(buffer, m_szTargetDir);
  746.             lstrcat(buffer, "\\");
  747.             lstrcat(buffer, m_szMainDir);
  748.             lstrcat(buffer, "\\");
  749.             lstrcat(buffer, UNINSTALL_FILE);
  750.             lstrcat(buffer, "\042");
  751.             AddMessage("   ");
  752.             AddMessage(m_szUninstallName);
  753.             AddMessage("=");
  754.             AddMessage(buffer);
  755.             AddMessage("\n");
  756.             RegSetValueEx(hsubkey, UNINSTALLSTRINGKEY, 0, REG_SZ,
  757.                 (CONST BYTE *)buffer, lstrlen(buffer)+1);
  758.             RegCloseKey(hsubkey);
  759.         }
  760.         
  761.         RegCloseKey(hkey);
  762.     }
  763.     return TRUE;
  764. }
  765.  
  766.  
  767. void
  768. CInstall::CopyFileContents(FILE *df, FILE *sf)
  769. {
  770.     char buf[MAXSTR];
  771.     int count;
  772.     while ((count = fread(buf, 1, sizeof(buf), sf)) != 0)
  773.         fwrite(buf, 1, count, df);
  774. }
  775.  
  776. FILE *CInstall::MakeTemp(char *fname)
  777. {
  778.     char *temp;
  779.     if ( (temp = getenv("TEMP")) == NULL )
  780.         strcpy(fname, m_szTargetDir);
  781.     else
  782.         strcpy(fname, temp);
  783.     
  784.     /* Prevent X's in path from being converted by mktemp. */
  785.     for ( temp = fname; *temp; temp++ ) {
  786.         *temp = (char)tolower(*temp);
  787.         if (*temp == '/')
  788.             *temp = '\\';
  789.     }
  790.     if ( strlen(fname) && (fname[strlen(fname)-1] != '\\') )
  791.         strcat(fname, "\\");
  792.     
  793.     strcat(fname, "gsXXXXXX");
  794.     mktemp(fname);
  795.     AddMessage("Creating temporary file ");
  796.     AddMessage(fname);
  797.     AddMessage("\n");
  798.     return fopen(fname, "w");
  799. }
  800.  
  801. BOOL CInstall::MakeLog()
  802. {
  803.     FILE *f, *lf;
  804.     char szFileName[MAXSTR];
  805.     char szLogDir[MAXSTR];
  806.     strcpy(szLogDir, m_szTargetDir);
  807.     strcat(szLogDir, "\\");
  808.     strcat(szLogDir, m_szMainDir);
  809.     strcat(szLogDir, "\\");
  810.     
  811.     strcpy(szFileName, szLogDir);
  812.     strcat(szFileName, UNINSTALL_FILE);
  813.     lf = fopen(szFileName, "w");
  814.     if (lf == (FILE *)NULL) {
  815.         AddMessage("Can't create uninstall log");
  816.         CleanUp();
  817.         return FALSE;
  818.     }
  819.     fputs(szSection, lf);
  820.     fputs("UninstallName\n", lf);
  821.     fputs(m_szUninstallName, lf);
  822.     fputs("\n\n", lf);
  823.     
  824.     if (strlen(m_szRegistryNew) &&
  825.         (f = fopen(m_szRegistryNew, "r")) != (FILE *)NULL) {
  826.         fputs(szSection, lf);
  827.         fputs("RegistryNew\n", lf);
  828.         CopyFileContents(lf, f);
  829.         fputs("\n", lf);
  830.         fclose(f);
  831.         DeleteFile(m_szRegistryNew);
  832.         m_szRegistryNew[0] = '\0';
  833.     }
  834.     
  835.     if (strlen(m_szRegistryOld) &&
  836.         (f = fopen(m_szRegistryOld, "r")) != (FILE *)NULL) {
  837.         fputs(szSection, lf);
  838.         fputs("RegistryOld\n", lf);
  839.         CopyFileContents(lf, f);
  840.         fputs("\n", lf);
  841.         fclose(f);
  842.         DeleteFile(m_szRegistryOld);
  843.         m_szRegistryOld[0] = '\0';
  844.     }
  845.     
  846.     if (strlen(m_szShellNew) &&
  847.         (f = fopen(m_szShellNew, "r")) != (FILE *)NULL) {
  848.         fputs(szSection, lf);
  849.         fputs("ShellNew\n", lf);
  850.         CopyFileContents(lf, f);
  851.         fputs("\n", lf);
  852.         fclose(f);
  853.         DeleteFile(m_szShellNew);
  854.         m_szShellNew[0] = '\0';
  855.     }
  856.     
  857.     if (strlen(m_szShellOld) &&
  858.         (f = fopen(m_szShellOld, "r")) != (FILE *)NULL) {
  859.         fputs(szSection, lf);
  860.         fputs("ShellOld\n", lf);
  861.         CopyFileContents(lf, f);
  862.         fputs("\n", lf);
  863.         fclose(f);
  864.         DeleteFile(m_szShellOld);
  865.         m_szShellOld[0] = '\0';
  866.     }
  867.     
  868.     if (strlen(m_szFileNew) &&
  869.         (f = fopen(m_szFileNew, "r")) != (FILE *)NULL) {
  870.         fputs(szSection, lf);
  871.         fputs("FileNew\n", lf);
  872.         CopyFileContents(lf, f);
  873.         fputs("\n", lf);
  874.         fclose(f);
  875.         DeleteFile(m_szFileNew);
  876.         m_szFileNew[0] = '\0';
  877.     }
  878.     
  879.     fputs(szSection, lf);
  880.     fclose(lf);
  881.     
  882.     return TRUE;
  883. }
  884.  
  885. BOOL CInstall::GetPrograms(BOOL bUseCommon, char *buf, int buflen)
  886. {
  887.     // Get the directory for the Program menu. This is
  888.     // stored in the Registry under HKEY_CURRENT_USER\Software\
  889.     // Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Programs.
  890.     LONG rc;
  891.     HKEY hCU;    
  892.     DWORD dwType;    
  893.     ULONG ulSize = buflen;
  894.     HKEY hrkey = HKEY_CURRENT_USER;
  895.     if (bUseCommon)
  896.         hrkey = HKEY_LOCAL_MACHINE;
  897.     if (RegOpenKeyEx(hrkey, 
  898.         "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 
  899.         0,KEY_QUERY_VALUE,      
  900.         &hCU) == ERROR_SUCCESS)    {
  901.         rc = RegQueryValueEx( hCU,        
  902.             bUseCommon ? "Common Programs" : "Programs",        
  903.             NULL,        
  904.             &dwType,
  905.             (unsigned char *)buf,        
  906.             &ulSize);      
  907.         RegCloseKey(hCU);    
  908.         return TRUE;
  909.     }
  910.     return FALSE;
  911.     
  912. #ifdef NOTUSED
  913.     // This is an alternate version, but it needs 
  914.     // Internet Explorer 4.0 with Web Integrated Desktop.
  915.     // It does not work with the standard 
  916.     // Windows 95, Windows NT 4.0, Internet Explorer 3.0, 
  917.     // and Internet Explorer 4.0 without Web Integrated Desktop.
  918.     
  919.     HRESULT rc;
  920.     m_szPrograms[0] = '\0';
  921.     int nFolder = CSIDL_PROGRAMS;
  922.     if (bUseCommon)
  923.         nFolder = CSIDL_COMMON_PROGRAMS;
  924.     
  925.     rc = SHGetSpecialFolderPath(HWND_DESKTOP, m_szPrograms, 
  926.         nFolder, FALSE);
  927.     return (rc == NOERROR);
  928. #endif
  929.     
  930. }
  931.  
  932. BOOL CInstall::SetAllUsers(BOOL bUseCommon)
  933. {
  934.     m_bUseCommon = bUseCommon;
  935.     return GetPrograms(bUseCommon, m_szPrograms, sizeof(m_szPrograms));
  936. }
  937.  
  938.  
  939. //////////////////////////////////////////////////////////////////////
  940.